#include "taskpool.h"

Ticker ticker;

/*
typedef int (*Task_def)();
int front, rear;
Tasks_def tasks_[Tasks_LEN];
// int hasTask_;
void addTask_(Tasks_def task)
{
	tasks_[rear++] = task;
	if (rear >= Tasks_LEN)
		rear = 0;
}

void endTask_(Tasks_def task) // trash
{
	int i;
	for (i = front; i != rear;)
	{
		if (tasks_[i] == task)
			break;
		i++;
		if (i == Tasks_LEN)
			i = 0;
	}
	if (i == rear)
		return;
	int j = i, next;
	while (j != rear)
	{
		next = j + 1;
		if (next == Tasks_LEN)
			next = 0;
		tasks_[j] = tasks_[next];
		j = next;
	}
}
void endTaskAt_(char index)
{
	int j = index, next;
	while (j != rear)
	{
		next = j + 1;
		if (next == Tasks_LEN)
			next = 0;
		tasks_[j] = tasks_[next];
		j = next;
	}
}
// whether has a task in pool
// return the index of a task, if any
char hadTask_(Tasks_def task)
{
	char b = 0;
	char i;

	for (i = front; i != rear;)
	{
		if (tasks_[i] == task)
		{
			b = i;
			break;
		}

		if (++i == Tasks_LEN)
			i = 0;
	}
	return b;
}

#define queue_len 16
static TasksArg_def fs_arg[queue_len];
static void *args[queue_len];
static char queue_front = 0, queue_back = 0;
int delegate_task_for_args();
void addTaskArg(TasksArg_def f, void *arg)
{
	fs_arg[queue_back] = f;
	args[queue_back++] = arg;
	if (queue_back >= queue_len)
		queue_back = 0;
	if (!hadTask_(delegate_task_for_args))
		addTask_(delegate_task_for_args);
}

int delegate_task_for_args()
{
	static int code;
	TasksArg_def f = fs_arg[queue_front];
	void *a = args[queue_front];
	code = f(a);   // 0->end, 1-> again
	if (code <= 0) // code==0
	{
		// if return 0, pop
		queue_front++;
		if (queue_front >= queue_len)
			queue_front = 0;
	}
	if (queue_back == queue_front)
		return 0;
	return 1;
}

#define quick_timer_len 8
Tasks_def quick_timer[quick_timer_len];
int quick_timer_count[quick_timer_len];
char quick_timer_size = 0;

#define Timer_len 16
struct Timer_def
{
	Task_def task;
	int peroids, ticks;
};
Timer_def timers[Timer_len];
int timer_count = 0;

static void lily_tick()
{

	int i, n;
	n = timer_count;
	for (i = 0; i < n; i++)
	{
		timers[i].ticks--;
		if (timers[i].ticks <= 0)
		{
			timers[i].ticks = timers[i].peroids;
			addTask_(timers[i].task);
		}
	}

	for (i = 0; i < quick_timer_size; i++)
	{
		if (--quick_timer_count[i] <= 0)
		{
			// swap
			addTask_(quick_timer[i]);
			quick_timer[i] = quick_timer[quick_timer_size - 1];
			quick_timer_count[i--] = quick_timer_count[quick_timer_size - 1];

			// remove
			quick_timer_size--;
			// i--;
		}
	}
}

static int add_timer_once(Tasks_def task, int count)
{
	quick_timer[quick_timer_size] = task;
	quick_timer_count[quick_timer_size++] = count;
	if (quick_timer_size >= quick_timer_len)
	{
		quick_timer_size = 0;
		// lily_out("\aquick timer overflow\n");
		return -1;
	}
	return 0;
}
static int change_quick_timer_count(Tasks_def timer, int newCount)
{
	int i;
	for (i = 0; i < quick_timer_size; i++)
	{
		if (quick_timer[i] == timer)
		{
			quick_timer_count[i] = newCount;
			return 0;
		}
	}
	return -1;
}
// once time
static int create_or_change_quick_timer_count(Tasks_def timer, int newCount)
{
	int i;
	for (i = 0; i < quick_timer_size; i++)
	{
		if (quick_timer[i] == timer)
		{
			quick_timer_count[i] = newCount;
			return 0;
		}
	}
	return add_timer_once(timer, newCount);
}

static void public_a_timer(Tasks_def task, unsigned int period, int rand)
{
	timers[timer_count].peroids = period;
	timers[timer_count].task = task;
	timers[timer_count++].ticks = period + rand;
}
void remove_a_timer(Tasks_def task)
{
	for (int i = 0; i < timer_count; i++)
	{
		if (timers[i].task == task)
		{
			timers[i] = timers[timer_count - 1];
			timer_count--;
			break;
		}
	}
}


*/
// return index+1

int had_timer(Tasks_def task)
{
	return find_timer(task) + 1;
}
void change_timer_per(Tasks_def task, unsigned int newPer)
{
	int i;
	Li_timer ts = list_content(lily_timers, Li_timer_t);
	for (i = 0; i < lily_timers->count; i++)
	{
		if (ts[i].work == task)
		{
			ts[i].period = newPer;
			ts[i].tick = newPer;
			return;
		}
	}
}

bool in_ticking = false;
bool stop_schedule()
{
	if (!in_ticking)
		return false;
	in_ticking = false;
	ticker.detach();
	return true;
}
bool resume_schedule()
{
	if (in_ticking)
		return false;
	in_ticking = true;
	ticker.attach_ms(1, lily_tick);
	return true;
}
